package com.yxxmg.netty;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @author : yxxmg
 * @version : 1.0
 * @description :
 * @since : 2025/1/14
 */
@Slf4j
@Component
public class NettyWebsocketServer {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    private ChannelFuture channelFuture;

    @PostConstruct
    public void start() throws Exception {
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        // 因为使用 HTTP 协议，所以需要 HTTP编码器，解码器
                        pipeline.addLast(new HttpServerCodec());
                        // 以块方式，添加 chunkedWriter 处理器
                        pipeline.addLast(new ChunkedWriteHandler());
                        /**
                         * 1. http数据在传输中是分段的，HttpObjectAggregator 可以把多个段聚合起来 2. 这就是为什么当浏览器发送大量数据时，就会发出多次 http请求的原因
                         */
                        pipeline.addLast(new HttpObjectAggregator(8192));
                        // 保存用户ip
                        // pipeline.addLast(new HttpHeadersHandler());
                        pipeline.addLast(new WebSocketServerProtocolHandler("/chat"));

                        pipeline.addLast(new IdleStateHandler(60, 5, 0));
                        pipeline.addLast(new ChatHandler()); // 添加自定义handler
                    }
                });

            // Bind and start to accept incoming connections.
            channelFuture = b.bind(9091).sync();
            if (channelFuture.isSuccess()) {
                log.info("netty启动成功");
            }
            // 对通道关闭进行监听
            channelFuture.channel().closeFuture().sync();
        } finally {
            if (channelFuture != null && channelFuture.isSuccess()) {
                log.info("Netty server started on port 9091");
            } else {
                log.error("Netty server failed to start");
            }
        }
    }
}
